﻿using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace ICodeShare.UI.Controls
{
    /// <summary>
    /// 一个带内光圈的边框
    /// Content control that draws a glow around its inside.
    /// </summary>
    [TemplatePart(Name = PART_LeftGlow, Type = typeof(Border))]
    [TemplatePart(Name = PART_TopGlow, Type = typeof(Border))]
    [TemplatePart(Name = PART_RightGlow, Type = typeof(Border))]
    [TemplatePart(Name = PART_BottomGlow, Type = typeof(Border))]
    [TemplatePart(Name = PART_LeftGlowStop0, Type = typeof(GradientStop))]
    [TemplatePart(Name = PART_LeftGlowStop1, Type = typeof(GradientStop))]
    [TemplatePart(Name = PART_TopGlowStop0, Type = typeof(GradientStop))]
    [TemplatePart(Name = PART_TopGlowStop1, Type = typeof(GradientStop))]
    [TemplatePart(Name = PART_RightGlowStop0, Type = typeof(GradientStop))]
    [TemplatePart(Name = PART_RightGlowStop1, Type = typeof(GradientStop))]
    [TemplatePart(Name = PART_BottomGlowStop0, Type = typeof(GradientStop))]
    [TemplatePart(Name = PART_BottomGlowStop1, Type = typeof(GradientStop))]
    public class InnerGlowBorder : ContentControl
    {
        #region Constants
        private const string PART_LeftGlow = "PART_LeftGlow";
        private const string PART_TopGlow = "PART_TopGlow";
        private const string PART_RightGlow = "PART_RightGlow";
        private const string PART_BottomGlow = "PART_BottomGlow";
        private const string PART_LeftGlowStop0 = "PART_LeftGlowStop0";
        private const string PART_LeftGlowStop1 = "PART_LeftGlowStop1";
        private const string PART_TopGlowStop0 = "PART_TopGlowStop0";
        private const string PART_TopGlowStop1 = "PART_TopGlowStop1";
        private const string PART_RightGlowStop0 = "PART_RightGlowStop0";
        private const string PART_RightGlowStop1 = "PART_RightGlowStop1";
        private const string PART_BottomGlowStop0 = "PART_BottomGlowStop0";
        private const string PART_BottomGlowStop1 = "PART_BottomGlowStop1";
        #endregion

        #region Fields

        /// <summary>
        /// Stores the left glow border.
        /// </summary>
        private Border leftGlow;

        /// <summary>
        /// Stores the top glow border.
        /// </summary>
        private Border topGlow;

        /// <summary>
        /// Stores the right glow border.
        /// </summary>
        private Border rightGlow;

        /// <summary>
        /// Stores the bottom glow border.
        /// </summary>
        private Border bottomGlow;

        /// <summary>
        /// Stores the left glow stop 0;
        /// </summary>
        private GradientStop leftGlowStop0;

        /// <summary>
        /// Stores the left glow stop 1;
        /// </summary>
        private GradientStop leftGlowStop1;

        /// <summary>
        /// Stores the top glow stop 0;
        /// </summary>
        private GradientStop topGlowStop0;

        /// <summary>
        /// Stores the top glow stop 1;
        /// </summary>
        private GradientStop topGlowStop1;

        /// <summary>
        /// Stores the right glow stop 0;
        /// </summary>
        private GradientStop rightGlowStop0;

        /// <summary>
        /// Stores the right glow stop 1.
        /// </summary>
        private GradientStop rightGlowStop1;

        /// <summary>
        /// Stores the bottom glow stop 0;
        /// </summary>
        private GradientStop bottomGlowStop0;

        /// <summary>
        /// Stores the bottom glow stop 1.
        /// </summary>
        private GradientStop bottomGlowStop1;

        #endregion

        #region Constructors

        static InnerGlowBorder()
        {
            //设置用于引用此控件的样式，方式一
            DefaultStyleKeyProperty.OverrideMetadata(typeof(InnerGlowBorder), new FrameworkPropertyMetadata(typeof(InnerGlowBorder)));
        }

        /// <summary>
        /// Initialises a new instance of the <see cref="InnerGlowBorder"/> class.
        /// </summary>
        public InnerGlowBorder()
        {
            //this.DefaultStyleKey = typeof(InnerGlowBorder);
        }

        #endregion

        #region Properties

        #region Dependency Properties

        #region InnerGlowColor 内光圈颜色

        /// <summary>
        /// 获取或设置内光圈颜色
        /// Gets or sets the inner glow colour.
        /// </summary>
        [Category("Appearance"), Description("The inner glow color.")]
        public Color InnerGlowColor
        {
            get { return (Color)this.GetValue(InnerGlowColorProperty); }
            set { this.SetValue(InnerGlowColorProperty, value); }
        }

        /// <summary>
        /// 内光圈颜色属性
        /// The inner glow colour.
        /// </summary>
        public static readonly DependencyProperty InnerGlowColorProperty = DependencyProperty.Register(
            "InnerGlowColor",
            typeof(Color),
            typeof(InnerGlowBorder),
            new PropertyMetadata(Colors.Black, OnInnerGlowColorChanged));

        /// <summary>
        /// Updates the inner glow colour when the DP changes.
        /// </summary>
        /// <param name="dependencyObject">The inner glow border.</param>
        /// <param name="eventArgs">The new property event args.</param>
        private static void OnInnerGlowColorChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs eventArgs)
        {
            InnerGlowBorder innerGlowBorder = (InnerGlowBorder)dependencyObject;
            innerGlowBorder.UpdateGlowColor((Color)eventArgs.NewValue);
        }

        #endregion

        #region InnerGlowOpacity 内光圈透明度

        /// <summary>
        /// 获取或设置内光圈透明度
        /// Gets or sets the inner glow opacity.
        /// </summary>
        [Category("Appearance"), Description("The inner glow opacity.")]
        public double InnerGlowOpacity
        {
            get { return (double)this.GetValue(InnerGlowOpacityProperty); }
            set { this.SetValue(InnerGlowOpacityProperty, value); }
        }

        /// <summary>
        /// 内光圈透明度属性
        /// The inner glow opacity property.
        /// </summary>
        public static readonly DependencyProperty InnerGlowOpacityProperty = DependencyProperty.Register(
            "InnerGlowOpacity",
            typeof(double),
            typeof(InnerGlowBorder),
            new PropertyMetadata(0.5));

        #endregion

        #region InnerGlowSize 内光圈大小

        /// <summary>
        /// 获取或设置内光圈大小
        /// Gets or sets the inner glow size.
        /// </summary>
        [Category("Appearance"), Description("The inner glow size.")]
        public Thickness InnerGlowSize
        {
            get { return (Thickness)this.GetValue(InnerGlowSizeProperty); }
            set{ this.SetValue(InnerGlowSizeProperty, value); }
        }

        /// <summary>
        /// 内光圈大小属性
        /// The inner glow size property.
        /// </summary>
        public static readonly DependencyProperty InnerGlowSizeProperty = DependencyProperty.Register(
            "InnerGlowSize",
            typeof(Thickness),
            typeof(InnerGlowBorder),
            new PropertyMetadata(new Thickness(10.0), OnInnerGlowSizeChanged));

        /// <summary>
        /// Updates the glow size.
        /// </summary>
        /// <param name="dependencyObject">The inner glow border.</param>
        /// <param name="eventArgs">Dependency Property Changed Event Args</param>
        private static void OnInnerGlowSizeChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs eventArgs)
        {
            InnerGlowBorder innerGlowBorder = (InnerGlowBorder)dependencyObject;
            innerGlowBorder.UpdateGlowSize((Thickness)eventArgs.NewValue);
        }

        #endregion

        #region CornerRadius 边框圆角

        /// <summary>
        /// 获取或设置边框圆角
        /// Gets or sets the border corner radius.
        /// This is a thickness, as there is a problem parsing CornerRadius types.
        /// </summary>
        [Category("Appearance"), Description("Sets the corner radius on the border.")]
        public CornerRadius CornerRadius
        {
            get { return (CornerRadius)this.GetValue(CornerRadiusProperty); }
            set { this.SetValue(CornerRadiusProperty, value); }
        }

        /// <summary>
        /// 边框圆角属性
        /// The corner radius property.
        /// </summary>
        public static readonly DependencyProperty CornerRadiusProperty = DependencyProperty.Register(
            "CornerRadius",
            typeof(CornerRadius),
            typeof(InnerGlowBorder),
            new PropertyMetadata(new CornerRadius(0.0)));

        #endregion

        #region ClipContent 是否裁剪内容

        /// <summary>
        /// 获取或设置是否裁剪内容
        /// Gets or sets a value indicating whether the content is clipped.
        /// </summary>
        [Category("Appearance"), Description("Sets whether the content is clipped or not.")]
        public bool ClipContent
        {
            get { return (bool)this.GetValue(ClipContentProperty); }
            set { this.SetValue(ClipContentProperty, value); }
        }

        /// <summary>
        /// 是否裁剪内容属性
        /// The clip content property.
        /// </summary>
        public static readonly DependencyProperty ClipContentProperty = DependencyProperty.Register(
            "ClipContent",
            typeof(bool),
            typeof(InnerGlowBorder),
            new PropertyMetadata(true));

        #endregion

        #region ContentZIndex 内容堆叠顺序

        /// <summary>
        /// 获取或设置内容堆叠顺序
        /// Gets or sets the content z-index. 0 for behind shadow, 1 for in-front.
        /// </summary>
        [Category("Appearance"), Description("Set 0 for behind the shadow, 1 for in front.")]
        public int ContentZIndex
        {
            get { return (int)this.GetValue(ContentZIndexProperty); }
            set { this.SetValue(ContentZIndexProperty, value); }
        }
        /// <summary>
        /// 内容堆叠顺序
        /// The content z-index property.
        /// </summary>
        public static readonly DependencyProperty ContentZIndexProperty = DependencyProperty.Register(
            "ContentZIndex",
            typeof(int),
            typeof(InnerGlowBorder),
            new PropertyMetadata(0));

        #endregion

        #endregion

        #endregion

        /// <summary>
        /// Gets the template parts out.
        /// </summary>
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            this.leftGlow = GetTemplateChild(PART_LeftGlow) as Border;
            this.topGlow = GetTemplateChild(PART_TopGlow) as Border;
            this.rightGlow = GetTemplateChild(PART_RightGlow) as Border;
            this.bottomGlow = GetTemplateChild(PART_BottomGlow) as Border;

            this.leftGlowStop0 = GetTemplateChild(PART_LeftGlowStop0) as GradientStop;
            this.leftGlowStop1 = GetTemplateChild(PART_LeftGlowStop1) as GradientStop;
            this.topGlowStop0 = GetTemplateChild(PART_TopGlowStop0) as GradientStop;
            this.topGlowStop1 = GetTemplateChild(PART_TopGlowStop1) as GradientStop;
            this.rightGlowStop0 = GetTemplateChild(PART_RightGlowStop0) as GradientStop;
            this.rightGlowStop1 = GetTemplateChild(PART_RightGlowStop1) as GradientStop;
            this.bottomGlowStop0 = GetTemplateChild(PART_BottomGlowStop0) as GradientStop;
            this.bottomGlowStop1 = GetTemplateChild(PART_BottomGlowStop1) as GradientStop;

            this.UpdateGlowColor(this.InnerGlowColor);
            this.UpdateGlowSize(this.InnerGlowSize);
        }

        /// <summary>
        /// 设置内光圈颜色
        /// Updates the inner glow colour.
        /// </summary>
        /// <param name="color">The new colour.</param>
        internal void UpdateGlowColor(Color color)
        {
            if (this.leftGlowStop0 != null)
            {
                this.leftGlowStop0.Color = color;
            }

            if (this.leftGlowStop1 != null)
            {
                this.leftGlowStop1.Color = Color.FromArgb(
                    0,
                    color.R,
                    color.G,
                    color.B);
            }

            if (this.topGlowStop0 != null)
            {
                this.topGlowStop0.Color = color;
            }

            if (this.topGlowStop1 != null)
            {
                this.topGlowStop1.Color = Color.FromArgb(
                    0,
                    color.R,
                    color.G,
                    color.B);
            }

            if (this.rightGlowStop0 != null)
            {
                this.rightGlowStop0.Color = color;
            }

            if (this.rightGlowStop1 != null)
            {
                this.rightGlowStop1.Color = Color.FromArgb(
                    0,
                    color.R,
                    color.G,
                    color.B);
            }

            if (this.bottomGlowStop0 != null)
            {
                this.bottomGlowStop0.Color = color;
            }

            if (this.bottomGlowStop1 != null)
            {
                this.bottomGlowStop1.Color = Color.FromArgb(
                    0,
                    color.R,
                    color.G,
                    color.B);
            }
        }

        /// <summary>
        /// 设置内光圈的上下左右宽度
        /// Sets the glow size.
        /// </summary>
        /// <param name="newGlowSize">The new glow size.</param>
        internal void UpdateGlowSize(Thickness newGlowSize)
        {
            if (this.leftGlow != null)
            {
                this.leftGlow.Width = Math.Abs(newGlowSize.Left);
            }

            if (this.topGlow != null)
            {
                this.topGlow.Height = Math.Abs(newGlowSize.Top);
            }

            if (this.rightGlow != null)
            {
                this.rightGlow.Width = Math.Abs(newGlowSize.Right);
            }

            if (this.bottomGlow != null)
            {
                this.bottomGlow.Height = Math.Abs(newGlowSize.Bottom);
            }
        }
    }
}